using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;

namespace XGAE.Framework.Extensions
{
    class Taxonomy<I,T>
    {
        public TreeNode<int, string> _root;

        public Taxonomy()
        {
            this.Reset();
        }

        public Taxonomy(string fileName)
        {
            this.Load(fileName);
        }

        public class TreeNode<K, V> : IEnumerable<TreeNode<K, V>>
        {
            private K _key;

            public K Key
            {
                get { return this._key; }
            }

            private V _value;

            public V Value
            {
                get { return this._value; }
            }

            private List<TreeNode<K,V>> _chields = new List<TreeNode<K,V>>();

            public List<TreeNode<K,V>> Chields
            {
                get { return this._chields; }
            }

            private TreeNode<K, V> _parent;

            public TreeNode<K, V> Parent
            {
                get { return this._parent; }
            }

            public TreeNode(K key, V value, TreeNode<K,V> parent)
            {
                this._key = key;
                this._value = value;
                this._parent = parent;
            }

            IEnumerator<TreeNode<K, V>> IEnumerable<TreeNode<K, V>>.GetEnumerator()
            {
                return this._chields.GetEnumerator();
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return this._chields.GetEnumerator();
            }
        }

        /// <summary>
        /// Provide a valid initial configuration with just a root node.
        /// </summary>
        public void Reset()
        {
            this._root = new TreeNode<int, string>(0, "entity", null);
        }

        public void Load(string fileName)
        {
            this.Reset();
            
            XmlDocument doc = new XmlDocument();

            try
            {
                doc.Load(fileName);
            }
            catch(IOException ex)
            {
                throw new Exception(ex.Message);
            }

            try
            {
                foreach(XmlNode n in doc.ChildNodes)
                    this.ParseXmlNode(n, ref this._root);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        private void ParseXmlNode(XmlNode node, ref TreeNode<int, string> tree)
        {           
            if (node.Attributes != null && null != node.Attributes["name"])
                tree.Chields.Add(new Taxonomy<I, T>.TreeNode<int, string>
                    ((tree.Key + 1), node.Attributes["name"].Value, tree));
                
            int cCount = tree.Chields.Count;

            if (node.HasChildNodes)
                foreach (XmlNode n in node.ChildNodes)
                {
                    TreeNode<int, string> c;
                    if (cCount != 0)
                        c = tree.Chields[cCount - 1];
                    else
                        c = tree;
                    this.ParseXmlNode(n, ref c);
                }
        }
    }
}
